package snuggle.jabber.utils;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Logger;
import org.jivesoftware.smack.SmackException.NotConnectedException;

public class FleetUpReader implements Runnable  {
	
	private URL url;
	private List<FleetUpEvent> events;
	private List<String> uids;
	private Timer timer;
	private Calendar cal;

	private static Logger logger = Logger.getLogger(FleetUpReader.class);
	
	@Override
	public void run() {
		logger.info("Fleet-Up Thread Started");
		
		ArrayList<String> oldUids;
		
		while(!Thread.currentThread().isInterrupted()) {
			try {
				oldUids = new ArrayList<String>(uids);
				
				parseEvents();
								
				for(FleetUpEvent event : events) {
					if( !oldUids.contains(event.getUid())) {
						logger.info("Event " + event.getUid() + " added.");
						createTimers(event);
					}
				}
				
				Thread.sleep(1000*60*30);
			} catch (InterruptedException e) {
				break;
			} catch (IOException | NotConnectedException | ParseException e) {
				logger.error(e.getMessage());
				e.printStackTrace();
			}
		}
	}

	public FleetUpReader(String fleetUpURL) throws IOException, ParseException {
		this.url = new URL(fleetUpURL);
		timer = new Timer();
		cal = Calendar.getInstance();
		uids = new ArrayList<String>();
	}
	
	private void createTimers(FleetUpEvent event) {
		TimerTask task = new ReminderTask(event.toString());
		
		Date date = event.getDate();
		
		cal.setTime(date);
		cal.add(Calendar.DATE, -1);
		Date timerDate = cal.getTime();
		
		if(timerDate.after(new Date())) {
			timer.schedule(task, timerDate);
			logger.info("Task scheduled for " + event.getUid() + " at " + timerDate);
		}
		
		cal.setTime(date);
		cal.add(Calendar.HOUR, -6);
		timerDate = cal.getTime();
		
		task = new ReminderTask(event.toString());
		
		if(timerDate.after(new Date())) {
			timer.schedule(task, timerDate);
			logger.info("Task scheduled for " + event.getUid() + " at " + timerDate);
		}
		
		task = new ReminderTask(event.toString());
		
		cal.setTime(date);
		cal.add(Calendar.HOUR, -1);
		timerDate = cal.getTime();
		
		if(timerDate.after(new Date())) {
			timer.schedule(task, timerDate);
			logger.info("Task scheduled for " + event.getUid() + " at " + timerDate);
		}
	}

	private void parseEvents() throws IOException, ParseException, NotConnectedException {
		logger.info("Parsing Fleet-Up Events...");
		
		uids = new ArrayList<String>();
				
		ReadableByteChannel rbc = Channels.newChannel(url.openStream());
		FileOutputStream fos = new FileOutputStream("calendar.ics");
		fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
		fos.close();
		rbc.close();

		BufferedReader in = new BufferedReader(new FileReader("calendar.ics"));

		boolean inEvent = false;
		String line = "";
		FleetUpEvent event = null;
		events = new ArrayList<FleetUpEvent>();

		while (null != (line = in.readLine())) {
			if (inEvent) {
				if (line.equals("END:VEVENT")) {
					events.add(event);
					uids.add(event.getUid());
					inEvent = false;
				} else if (line.startsWith("UID")) {
					event.setUid(line.substring(4));
				} else if (line.startsWith("DTSTAMP")) {
					event.setDate(line.substring(8));
				} else if (line.startsWith("ORGANIZER")) {
					event.setOrganizer(line.substring(line.indexOf(':') + 1));
				} else if (line.startsWith("SUMMARY")) {
					event.setTitle(line.substring(8, line.indexOf('(')));
				} else if (line.startsWith("URL")) {
					event.setUrl(line.substring(4));
				} else if (line.startsWith("DESCRIPTION")) {
					event.setDescription(line.substring(12));
				} else if (line.startsWith("LOCATION")) {
					event.setLocation(line.substring(9));
				}
			} else if (line.equals("BEGIN:VEVENT")) {
				event = new FleetUpEvent();
				inEvent = true;
			}
		}

		in.close();

		logger.info("Found " + events.size() + " Fleet-Up events.");
	}

}
